﻿using System.Xml.Linq;

namespace EasyXaf.DynamicForm.Models;

public abstract class Element
{
    public string Id { get; }

    public string ReadOnly { get; set; }

    public string Visible { get; set; }

    public bool ActualVisible { get; set; }

    public bool ActualReadOnly { get; set; }

    public bool IsCurrentlyReadOnly
    {
        get
        {
            if (ActualReadOnly)
            {
                return true;
            }

            if (Parent is Element parent)
            {
                return parent.IsCurrentlyReadOnly;
            }

            return false;
        }
    }

    public Element Parent { get; set; }

    public Dictionary<string, string> Attributes { get; }

    public Element(Element parent)
    {
        Id = "id-" + Guid.NewGuid().ToString();
        Parent = parent;
        Attributes = [];
    }

    protected static void SetXmlAttributeValue<T>(XElement element, string name, T value)
    {
        element.SetAttributeValue(name, value);
    }

    protected static T GetXmlAttributeValue<T>(XElement element, string name, T defaultValue = default)
    {
        if (element.Attribute(name) is XAttribute attribute)
        {
            return (T)(dynamic)attribute;
        }
        return defaultValue;
    }

    public virtual void WriteXml(XElement element)
    {
        if (!string.IsNullOrWhiteSpace(ReadOnly))
        {
            SetXmlAttributeValue(element, "readonly", ReadOnly);
        }

        if (!string.IsNullOrWhiteSpace(Visible))
        {
            SetXmlAttributeValue(element, "visible", Visible);
        }

        foreach (var attribute in Attributes)
        {
            SetXmlAttributeValue(element, attribute.Key, attribute.Value);
        }
    }

    public virtual void ReadXml(XElement element)
    {
        ReadOnly = GetXmlAttributeValue<string>(element, "readonly");
        Visible = GetXmlAttributeValue<string>(element, "visible");

        Attributes.Clear();

        foreach (var attribute in element.Attributes())
        {
            Attributes[attribute.Name.LocalName] = attribute.Value;
        }
    }

    public abstract XElement CreateXElement();
}
